package com.link.base.base.statistics.service;

import com.link.base.base.forum.dao.mybatis.mapper.ForumMapper;
import com.link.base.base.forum.model.Forum;
import com.link.base.base.knowledge.dao.mybatis.mapper.KnowledgeMapper;
import com.link.base.base.knowledge.model.Knowledge;
import com.link.base.base.product.dao.mybatis.mapper.PortalProductCaseMapper;
import com.link.base.base.product.model.PortalProductCase;
import com.link.base.base.statistics.dao.mybatis.mapper.StatisticsMapper;
import com.link.base.base.statistics.model.Statistics;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.KeyGenerateService;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.RedisUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.redisclient.LinkRedisClient;
import org.springframework.stereotype.Component;


import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;

/**
 * 存储知识库、论坛帖子、案例库等对象用户浏览、阅读、收藏、点赞记录
 *
 * @author ouyangzhenqiang
 * @date 2018/11/6
 */
@Component
public class StatisticsServiceImpl extends BasicServiceImpl<Statistics> implements StatisticsService {
    /**
     * 支持的模块
     * forum -- 论坛帖子
     * knowledgeBase -- 知识库
     * caseBase -- 案例库
     */
    private static List<String> moduleList = Arrays.asList("forum", "knowledgeBase", "caseBase");
    /**
     * 支持的数据统计类别
     * pageView -- 浏览量和阅读数
     * thumb -- 点赞
     * collect -- 收藏
     */
    private static List<String> typeList = Arrays.asList("pageView", "thumb", "collect");

    @Resource
    private StatisticsMapper statisticsMapper;
    @Resource
    private KeyGenerateService keyGenerateService;
    @Resource
    private KnowledgeMapper knowledgeMapper;
    @Resource
    private ForumMapper forumMapper;
    @Resource
    private PortalProductCaseMapper portalProductCaseMapper;

    @Override
    public Statistics increasePageView(Statistics record) throws Exception {
        LinkRedisClient j = RedisUtil.getJedis();
        try {
            // 校验核心数据
            check(record);
            String recordKey = "rowId_" + record.getModuleId();
            String pageViewRedisKey = "pageView_" + record.getModuleName() + ":" + record.getModuleId();
            // 浏览量总数Hash Key
            String pageViewTotalNumKey = "pageViewTotalNum";
            // 阅读人数Hash Key
            String readNumTotalNumKey = "readNumTotalNum";
            if (StringUtils.isBlank(j.hget(pageViewRedisKey, recordKey))) {
                j.hset(pageViewRedisKey, recordKey, String.valueOf(record.getModuleId()));
            }
            // 记录浏览用户
            String userKey = "user_" + record.getUserId();
            String readTotalNum = j.hget(pageViewRedisKey, readNumTotalNumKey);
            if (StringUtils.isBlank(j.hget(pageViewRedisKey, userKey))) {
                j.hset(pageViewRedisKey, userKey, String.valueOf(record.getUserId()));
                // 记录总阅读人数
                if (StringUtils.isBlank(readTotalNum)) {
                    readTotalNum = "1";
                } else {
                    readTotalNum = String.valueOf(Integer.valueOf(readTotalNum) + 1);
                }
                j.hset(pageViewRedisKey, readNumTotalNumKey, readTotalNum);
                // 将用户浏览/阅读记录维护到DB
                record.setId(keyGenerateService.keyGenerate());
                record.setUserAction("pageView");
                statisticsMapper.insert(record);
            }
            // 记录总浏览数
            String pageViewTotalNum = j.hget(pageViewRedisKey, pageViewTotalNumKey);
            if (StringUtils.isBlank(pageViewTotalNum)) {
                pageViewTotalNum = "1";
            } else {
                pageViewTotalNum = String.valueOf(Integer.valueOf(pageViewTotalNum) + 1);
            }
            j.hset(pageViewRedisKey, pageViewTotalNumKey, pageViewTotalNum);
            // 返回浏览数和阅读人数
            Statistics statistics = new Statistics();
            statistics.setPageViewNum(Integer.valueOf(pageViewTotalNum));
            statistics.setReadNum(Integer.valueOf((readTotalNum)));
            return statistics;
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    @Override
    public String dealDataForThumbAndCollect(String type, Statistics record) throws Exception {
        LinkRedisClient j = RedisUtil.getJedis();
        try {
            // 校验核心数据
            check(record);
            String redisKey = type + "_" + record.getModuleName() + ":" + record.getModuleId();
            String recordKey = "rowId_" + record.getModuleId();
            String totalNumKey = type + "TotalNum";
            String userKey = "user_" + record.getUserId();
            if (StringUtils.isBlank(j.hget(redisKey, recordKey))) {
                j.hset(redisKey, recordKey, String.valueOf(record.getModuleId()));
            }
            // 判断用户是否点赞/收藏
            boolean isAdd;
            if (StringUtils.isBlank(j.hget(redisKey, userKey))) {
                isAdd = true;
                j.hset(redisKey, userKey, String.valueOf(record.getUserId()));
                record.setId(keyGenerateService.keyGenerate());
                record.setUserAction(type);
                statisticsMapper.insert(record);
            } else {
                isAdd = false;
                j.hdel(redisKey, userKey);
                record.setUserAction(type);
                statisticsMapper.delRecordByModuleIdAndUserId(record);
            }
            // 处理点赞/收藏总数
            String totalNum = j.hget(redisKey, totalNumKey);
            if (StringUtils.isBlank(totalNum)) {
                if (isAdd) {
                    totalNum = "1";
                } else {
                    totalNum = "0";
                }
            } else {
                int temp = Integer.valueOf(totalNum);
                if (isAdd) {
                    totalNum = String.valueOf(temp + 1);
                } else {
                    if (temp > 0) {
                        totalNum = String.valueOf(temp - 1);
                    } else {
                        totalNum = "0";
                    }
                }
            }
            j.hset(redisKey, totalNumKey, totalNum);
            return totalNum;
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    @Override
    public Statistics getStatisticsByModuleRecord(String moduleName, Long moduleId) throws Exception {
        LinkRedisClient j = RedisUtil.getJedis();
        try {
            if (!moduleList.contains(moduleName)) {
                throw new ServiceException("SOTCKSELLSTORAGE-001");
            }
            Statistics record = new Statistics();
            for (String type : typeList) {
                String redisKey = type + "_" + moduleName + ":" + moduleId;
                String totalNumKey = type + "TotalNum";
                String TotalNum = j.hget(redisKey, totalNumKey);
                // 赋值浏览量/阅读量/点赞量/收藏量
                if (StringUtils.isNotBlank(TotalNum)) {
                    if ("pageView".equals(type)) {
                        record.setPageViewNum(Integer.valueOf(TotalNum));
                        String readNum = j.hget(redisKey, "readNumTotalNum");
                        if (StringUtils.isNotBlank(readNum)) {
                            record.setReadNum(Integer.valueOf(readNum));
                        }
                    } else if ("thumb".equals(type)) {
                        record.setThumbNum(Integer.valueOf(TotalNum));
                    } else if ("collect".equals(type)) {
                        record.setCollectNum(Integer.valueOf(TotalNum));
                    }
                }
            }
            return record;
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    @Override
    public Statistics getFlagByModuleAndUser(String moduleName, Long moduleId, Long userId) throws Exception {
        LinkRedisClient j = RedisUtil.getJedis();
        try {
            if (!moduleList.contains(moduleName)) {
                throw new ServiceException("SOTCKSELLSTORAGE-001");
            }
            Statistics record = new Statistics();
            for (String type : typeList) {
                String redisKey = type + "_" + moduleName + ":" + moduleId;
                String myRecordKey = "user_" + userId;
                String myRecord = j.hget(redisKey, myRecordKey);
                // 赋值是否点赞/收藏
                if (StringUtils.isNotBlank(myRecord)) {
                    if ("thumb".equals(type)) {
                        record.setIsThumb("Y");
                    } else if ("collect".equals(type)) {
                        record.setIsCollect("Y");
                    }
                }
            }
            return record;
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    @Override
    public void check(Statistics record) throws Exception {
        Long userId = record.getUserId();
        Long moduleId = record.getModuleId();
        String moduleName = record.getModuleName();
        if (null == userId) {
            throw new ServiceException("PUBLIC-016");
        }
        if (null == moduleId) {
            throw new ServiceException("STATISTICS-002");
        }
        if (StringUtils.isBlank(moduleName)) {
            throw new ServiceException("STATISTICS-003");
        } else {
            if (!moduleList.contains(moduleName)) {
                throw new ServiceException("STATISTICS-001");
            }
        }
    }

    @Override
    public void writeBackFromRedisToDB() throws Exception {
        LinkRedisClient j = RedisUtil.getJedis();
        try {
            String redisKey;
            Integer pageViews;
            Integer readNum;
            Integer thumbUpNum;
            Integer collNum;
            Knowledge knowledge = new Knowledge();
            List<Knowledge> knowledgeList = knowledgeMapper.queryAll(knowledge);
            for (Knowledge item: knowledgeList) {
                redisKey =  "pageView_knowledgeBase:" + item.getId();
                pageViews = getIntFromStr(j.hget(redisKey, "pageViewTotalNum"));
                readNum = getIntFromStr(j.hget(redisKey, "readNumTotalNum"));
                redisKey =  "thumb_knowledgeBase:" + item.getId();
                thumbUpNum = getIntFromStr(j.hget(redisKey, "thumbTotalNum"));
                redisKey =  "collect_knowledgeBase:" + item.getId();
                collNum = getIntFromStr(j.hget(redisKey, "collectTotalNum"));
                if (!pageViews.equals(item.getPageviews()) || !readNum.equals(item.getReadNum())
                    || !thumbUpNum.equals(item.getThumbUpNum()) || !collNum.equals(item.getCollNum())) {
                    item.setPageviews(pageViews);
                    item.setReadNum(readNum);
                    item.setThumbUpNum(thumbUpNum);
                    item.setCollNum(collNum);
                    knowledgeMapper.updateNum(item);
                }
            }
            Forum forum = new Forum();
            List<Forum> forumList = forumMapper.queryAll(forum);
            for (Forum item: forumList) {
                redisKey =  "pageView_forum:" + item.getId();
                pageViews = getIntFromStr(j.hget(redisKey, "pageViewTotalNum"));
                readNum = getIntFromStr(j.hget(redisKey, "readNumTotalNum"));
                redisKey =  "thumb_forum:" + item.getId();
                thumbUpNum = getIntFromStr(j.hget(redisKey, "thumbTotalNum"));
                redisKey =  "collect_forum:" + item.getId();
                collNum = getIntFromStr(j.hget(redisKey, "collectTotalNum"));
                if (!pageViews.equals(item.getPageviews()) || !readNum.equals(item.getReadNum())
                    || !thumbUpNum.equals(item.getFavorNum()) || !collNum.equals(item.getCollectNum())) {
                    item.setPageviews(pageViews);
                    item.setReadNum(readNum);
                    item.setFavorNum(thumbUpNum);
                    item.setCollectNum(collNum);
                    forumMapper.updateNum(item);
                }
            }
            PortalProductCase portalProductCase = new PortalProductCase();
            List<PortalProductCase> portalProductCaseList = portalProductCaseMapper.queryAll(portalProductCase);
            for (PortalProductCase item: portalProductCaseList) {
                redisKey =  "pageView_caseBase:" + item.getId();
                pageViews = getIntFromStr(j.hget(redisKey, "pageViewTotalNum"));
                readNum = getIntFromStr(j.hget(redisKey, "readNumTotalNum"));
                redisKey =  "thumb_caseBase:" + item.getId();
                thumbUpNum = getIntFromStr(j.hget(redisKey, "thumbTotalNum"));
                redisKey =  "collect_caseBase:" + item.getId();
                collNum = getIntFromStr(j.hget(redisKey, "collectTotalNum"));
                if (!pageViews.equals(item.getPageviews()) || !readNum.equals(item.getReadNum())
                    || !thumbUpNum.equals(item.getThumbUpNum()) || !collNum.equals(item.getCollNum())) {
                    item.setPageviews(pageViews);
                    item.setReadNum(readNum);
                    item.setThumbUpNum(thumbUpNum);
                    item.setCollNum(collNum);
                    portalProductCaseMapper.updateNum(item);
                }
            }
        } finally {
            RedisUtil.returnResource(j);
        }
    }

    /**
     * 判断字符串是否为null，为null则返回整数0，否则返回字符串取整
     *
     * @author ouyangzhenqiang
     * @date 2019/03/08 11:35
     */
    Integer getIntFromStr(String str) throws Exception {
        if (StringUtils.isNotBlank(str)) {
            return Integer.valueOf(str);
        }
        return 0;
    }
}
